{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Option pricing with the Heston / Hull White model"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "##The model"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The Heston / Hull-White model is a Heston model, where the dynamic of the risk-free rate is governed by a Hull-White one-factor model:"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\\begin{align}\n",
    "\\frac{dS}{S}& = (r_t - \\nu) dt + \\sqrt{V_t} dZ_t \\\\\n",
    "dV_t& = \\kappa_V(\\theta_V - V_t) dt + \\sigma_V \\sqrt{V_t} dW^1_t \\\\\n",
    "dr_t& = \\kappa_r(\\theta_r(t) - r_t) dt + \\sigma_r dW^2_t\n",
    "\\end{align}\n",
    "\n",
    "with:\n",
    "\n",
    "\\begin{equation}\n",
    "<Z_t, W^1_t> = \\rho_1 \\ \\ \\ \\  <Z_t, W^2_t> = \\rho_2\n",
    "\\end{equation}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Illustration"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The QuantLib open source library implements a finite-difference option pricer for the Heston / Hull-White model. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "\n",
    "from quantlib.settings import Settings\n",
    "\n",
    "from quantlib.instruments.option import (\n",
    "    EuropeanExercise, VanillaOption)\n",
    "\n",
    "from quantlib.instruments.payoffs import (\n",
    "    PlainVanillaPayoff, Put, Call, PAYOFF_TO_STR)\n",
    "\n",
    "from quantlib.models.shortrate.onefactormodels.hullwhite import HullWhite\n",
    "\n",
    "from quantlib.time.api import (today, Years, Actual365Fixed,\n",
    "                               Period, May, Date,\n",
    "                               NullCalendar)\n",
    "\n",
    "from quantlib.processes.api import (BlackScholesMertonProcess,\n",
    "                                    HestonProcess,\n",
    "                                    HullWhiteProcess)\n",
    "\n",
    "from quantlib.models.equity.heston_model import (\n",
    "    HestonModel)\n",
    "\n",
    "from quantlib.termstructures.yields.api import ZeroCurve, FlatForward\n",
    "from quantlib.termstructures.volatility.api import BlackConstantVol\n",
    "\n",
    "from quantlib.pricingengines.api import (\n",
    "    AnalyticEuropeanEngine,\n",
    "    AnalyticBSMHullWhiteEngine,\n",
    "    AnalyticHestonEngine,\n",
    "    AnalyticHestonHullWhiteEngine,\n",
    "    FdHestonHullWhiteVanillaEngine)\n",
    "\n",
    "from quantlib.quotes import SimpleQuote\n",
    "\n",
    "from quantlib.methods.finitedifferences.solvers.fdmbackwardsolver import FdmSchemeDesc"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We reproduce here the numerical experiment presented by Briani, Caramellino and Zanette [](#cite-Briani2015). The calculations are found in Table 1, p. 14."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Data"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* initial share price $S_0 = 100$, strike price $K = 100$, maturity $T = 1$, dividend rate $\\nu = 0.03$; \n",
    "* initial interest rate $r_0 = 0.04$, speed of mean-reversion $\\kappa_r = 1$, interest rate volatility $\\sigma_r = 0.2$;\n",
    "* initial volatility $V_0 = 0.1$, long-mean $\\theta_V = 0.1$, speed of mean-reversion $\\kappa_V = 2$, volatility of volatility $\\sigma_V = 0.3$.\n",
    "\n",
    "The zero-coupon yield curve is flat ($4\\%$), and so is the dividend yield curve ($3\\%$).\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "        dc = Actual365Fixed()\n",
    "\n",
    "        todays_date = today()\n",
    "        settings = Settings()\n",
    "        settings.evaluation_date = todays_date\n",
    "\n",
    "        # constant yield and div curves\n",
    "\n",
    "        dates = [todays_date + Period(i, Years) for i in range(3)]\n",
    "        rates = [0.04 for i in range(3)]\n",
    "        divRates = [0.03 for i in range(3)]\n",
    "        r_ts = ZeroCurve(dates, rates, dc)\n",
    "        q_ts = ZeroCurve(dates, divRates, dc)\n",
    "\n",
    "        s0 = SimpleQuote(100)\n",
    "\n",
    "        # Heston model\n",
    "\n",
    "        v0 = .1\n",
    "        kappa_v = 2\n",
    "        theta_v = 0.1\n",
    "        sigma_v = 0.3\n",
    "        rho_sv = -0.5\n",
    "\n",
    "        hestonProcess = HestonProcess(\n",
    "            risk_free_rate_ts=r_ts,\n",
    "            dividend_ts=q_ts,\n",
    "            s0=s0,\n",
    "            v0=v0,\n",
    "            kappa=kappa_v,\n",
    "            theta=theta_v,\n",
    "            sigma=sigma_v,\n",
    "            rho=rho_sv)\n",
    "\n",
    "        hestonModel = HestonModel(hestonProcess)\n",
    "\n",
    "        # Hull-White model\n",
    "\n",
    "        kappa_r = 1\n",
    "        sigma_r = .2\n",
    "\n",
    "        hullWhiteProcess = HullWhiteProcess(r_ts, a=kappa_r, sigma=sigma_r)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We define a European option, maturity 1 year and strike $K=100$."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "        strike = 100\n",
    "        maturity = 1\n",
    "        type = Call\n",
    "\n",
    "        maturity_date = todays_date + Period(maturity, Years)\n",
    "\n",
    "        exercise = EuropeanExercise(maturity_date)\n",
    "\n",
    "        payoff = PlainVanillaPayoff(type, strike)\n",
    "\n",
    "        option = VanillaOption(payoff, exercise)\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The finite difference scheme involves a four-dimensional grid. The discretization is \n",
    "specified by the following parameters that define the mesh along each dimension: \n",
    "\n",
    "* tGrid: the time dimension\n",
    "* xGrid: the underlying asset\n",
    "* vGrid: the volatility in the heston process\n",
    "* rGrid: the rate process\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def price_cal(rho, tGrid, xGrid=100, vGrid=40, rGrid=20):\n",
    "            fd_hestonHwEngine = FdHestonHullWhiteVanillaEngine(\n",
    "                hestonModel,\n",
    "                hullWhiteProcess,\n",
    "                rho,\n",
    "                tGrid, xGrid, vGrid, rGrid, 0, True, FdmSchemeDesc.Hundsdorfer())\n",
    "            option.set_pricing_engine(fd_hestonHwEngine)\n",
    "            return option.npv"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "To reproduce Table 1 of [](#cite-Briani2015), we vary the stock-rate correlation from $-0.5$ to $0.5$. The resulting prices, for various time discretization levels, are displayed below. They are in very good agreement with the published results.  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[11.38, 11.38, 11.38, 11.38, 12.81, 12.81, 12.81, 12.81, 14.08, 14.08, 14.08, 14.08]\n"
     ]
    }
   ],
   "source": [
    "        calc_price = []\n",
    "        rho = [-0.5]*4 + [0]*4 + [0.5]*4\n",
    "        tGrid = [50, 100, 150, 200] * 3\n",
    "        \n",
    "        calc_price = [price_cal(r, t) for (r, t) in zip(rho, tGrid)]\n",
    "        \n",
    "        expected_price = [11.38, ] * 4 + [12.81, ] * 4 + [14.08, ] * 4\n",
    "\n",
    "        print(expected_price)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "  Computed Price    Published (AMC2)    Time Grid     Rho\n",
      "----------------  ------------------  -----------  ------\n",
      "          11.390              11.380           50  -0.500\n",
      "          11.390              11.380          100  -0.500\n",
      "          11.390              11.380          150  -0.500\n",
      "          11.390              11.380          200  -0.500\n",
      "          12.810              12.810           50   0.000\n",
      "          12.810              12.810          100   0.000\n",
      "          12.810              12.810          150   0.000\n",
      "          12.810              12.810          200   0.000\n",
      "          14.081              14.080           50   0.500\n",
      "          14.082              14.080          100   0.500\n",
      "          14.082              14.080          150   0.500\n",
      "          14.082              14.080          200   0.500\n"
     ]
    }
   ],
   "source": [
    "from tabulate import tabulate\n",
    "table = {\"Rho\":rho, \"Time Grid\":tGrid, \"Computed Price\":calc_price, \n",
    "         \"Published (AMC2)\": expected_price}\n",
    "print tabulate(table, headers='keys', floatfmt='.3f')"
   ]
  },
  {
   "cell_type": "raw",
   "metadata": {},
   "source": [
    "<!--bibtex\n",
    "\n",
    "@unpublished{Briani2015,\n",
    "abstract = {We study a hybrid tree-finite difference method which permits to obtain efficient and accurate European and American option prices in the Heston Hull-White and Heston Hull-White2d models. Moreover, as a by-product, we provide a new simulation scheme to be used for Monte Carlo evaluations. Numerical results show the reliability and the efficiency of the proposed methods},\n",
    "archivePrefix = {arXiv},\n",
    "arxivId = {1503.03705},\n",
    "author = {Briani, M. and Caramellino, L. and Zanette, A.},\n",
    "eprint = {1503.03705},\n",
    "file = {:home/phn/doc/library/Briani, Caramellino, Zanette - 2015.pdf:pdf},\n",
    "keywords = {european and american options,finite difference,monte carlo,stochastic interest rate,stochastic volatility,tree methods},\n",
    "pages = {1--22},\n",
    "title = {{Numerical approximations for Heston-Hull-White type models}},\n",
    "url = {http://arxiv.org/abs/1503.03705},\n",
    "year = {2015}\n",
    "}\n",
    "\n",
    "-->\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<!--bibtex\n",
    "\n",
    "@unpublished{Briani2015,\n",
    "abstract = {We study a hybrid tree-finite difference method which permits to obtain efficient and accurate European and American option prices in the Heston Hull-White and Heston Hull-White2d models. Moreover, as a by-product, we provide a new simulation scheme to be used for Monte Carlo evaluations. Numerical results show the reliability and the efficiency of the proposed methods},\n",
    "archivePrefix = {arXiv},\n",
    "arxivId = {1503.03705},\n",
    "author = {Briani, M. and Caramellino, L. and Zanette, A.},\n",
    "eprint = {1503.03705},\n",
    "file = {:home/phn/doc/library/Briani, Caramellino, Zanette - 2015.pdf:pdf},\n",
    "keywords = {european and american options,finite difference,monte carlo,stochastic interest rate,stochastic volatility,tree methods},\n",
    "pages = {1--22},\n",
    "title = {{Numerical approximations for Heston-Hull-White type models}},\n",
    "url = {http://arxiv.org/abs/1503.03705},\n",
    "year = {2015}\n",
    "}\n",
    "\n",
    "-->"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 2",
   "language": "python",
   "name": "python2"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
